package com.fhs.trans.config;

import com.fhs.cache.service.RedisCacheService;
import com.fhs.cache.service.impl.RedisCacheServiceImpl;
import com.fhs.common.spring.SpringContextUtil;
import com.fhs.core.trans.constant.TransType;
import com.fhs.trans.aop.TransMethodResultAop;
import com.fhs.trans.extend.JPATransableRegister;
import com.fhs.trans.extend.MybatisPlusTransableRegister;
import com.fhs.trans.listener.TransMessageListener;
import com.fhs.trans.service.DictionaryTransCustomizer;
import com.fhs.trans.service.TransableRegister;
import com.fhs.trans.service.impl.AutoTransService;
import com.fhs.trans.service.impl.DictionaryTransService;
import com.fhs.trans.service.impl.ITransTypeService;
import com.fhs.trans.service.impl.TransService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Slf4j
@ComponentScan("com.fhs.trans")
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class TransServiceConfig {

    /**
     * 翻译服务主服务
     *
     * @return
     */
    @Bean
    public TransService transService(ObjectProvider<List<ITransTypeService>> objectProvider) {

        return new TransService();
    }

    /**
     * 自动翻译服务
     *
     * @return
     */
    @Bean
    @DependsOn("springContextUtil")
    @ConditionalOnProperty(name = "easy-trans.autotrans.package-names")
    public AutoTransService autoTransService(TransServiceProperties transServiceProperties) {
        AutoTransService autoTransService = new AutoTransService();
        autoTransService.setTransConfig(transServiceProperties);
        return autoTransService;
    }


    @Bean
    @ConditionalOnMissingBean(TransableRegister.class)
    @ConditionalOnProperty(name = "easy-trans.autotrans.package-names")
    public DefaultTransableRegister defaultTransableRegister(TransServiceProperties properties) {
        DefaultTransableRegister result = new DefaultTransableRegister();
        result.setPackageNames(properties.getPackageNames());
        return result;
    }

    @Configuration
    @ConditionalOnClass(MybatisPlusTransableRegister.class)
    @ConditionalOnProperty(name = "easy-trans.autotrans.package-names")
    public static class MybatisPlusEasyTransConfig {

        @Bean("mybatisPlusTransRegister")
        public MybatisPlusTransableRegister mybatisPlusTransableRegister(TransServiceProperties properties) {
            MybatisPlusTransableRegister result = new MybatisPlusTransableRegister();
            result.setPackageNames(properties.getPackageNames());
            return result;
        }

    }

    @Configuration
    @ConditionalOnClass(JPATransableRegister.class)
    @ConditionalOnProperty(name = "easy-trans.autotrans.package")
    public static class JpaEasyTransConfig {

        @Bean
        public JPATransableRegister JpaTransableRegister(TransServiceProperties properties) {
            JPATransableRegister result = new JPATransableRegister();
            result.setPackageNames(properties.getPackageNames());
            return result;
        }

    }

    /**
     * 字典翻译服务
     *
     * @return
     */
    @Bean
    public DictionaryTransService dictionaryTransService(ObjectProvider<List<DictionaryTransCustomizer>> dictionaryTransCustomizeres,
                                                         ObjectProvider<RedisCacheService<String>> redisCacheServices,
                                                         TransServiceProperties transServiceProperties) {
        DictionaryTransService dictionaryTransService = new DictionaryTransService();
        dictionaryTransService.setTransConfig(transServiceProperties);
        dictionaryTransService.setRedisTransCache(redisCacheServices.getIfAvailable());
        List<DictionaryTransCustomizer> dictionaryTransCustomizers = dictionaryTransCustomizeres.getIfAvailable();
        if (!CollectionUtils.isEmpty(dictionaryTransCustomizers)) {
            dictionaryTransCustomizers.forEach(e -> {
                dictionaryTransService.registerDictionary(e);
            });
        }

        return dictionaryTransService;
    }

    /**
     * 自动翻译方法结果aop
     *
     * @return
     */
    @Bean
    public TransMethodResultAop transMethodResultAop() {
        return new TransMethodResultAop();
    }

    @Bean
    @ConditionalOnProperty(name = "easy-trans.autotrans.enable-redis", havingValue = "true")
    public TransMessageListener transMessageListener() {
        return new TransMessageListener();
    }

    /**
     * redis消息监听器容器
     * 可以添加多个监听不同话题的redis监听器，只需要把消息监听器和相应的消息订阅处理器绑定，该消息监听器
     * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
     *
     * @param connectionFactory redis连接池
     * @param listenerAdapter   监听适配器
     * @return
     */
    @Bean
    @ConditionalOnProperty(name = "easy-trans.autotrans.enable-redis", havingValue = "true")
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        //订阅多个频道
        container.addMessageListener(listenerAdapter, new PatternTopic("trans"));
        //序列化对象（特别注意：发布的时候需要设置序列化；订阅方也需要设置序列化）
        StringRedisSerializer seria = new StringRedisSerializer();
        container.setTopicSerializer(seria);
        return container;
    }

    //表示监听一个频道
    @Bean
    @ConditionalOnProperty(name = "easy-trans.autotrans.enable-redis", havingValue = "true")
    MessageListenerAdapter listenerAdapter(TransMessageListener receiver) {
        MessageListenerAdapter result = new MessageListenerAdapter(receiver, "handelMsg");
        JdkSerializationRedisSerializer valSerializer = new JdkSerializationRedisSerializer();
        result.setSerializer(valSerializer);
        return result;
    }

    @Bean(TransType.AUTO_TRANS+"RedisCache")
    @ConditionalOnProperty(name = "easy-trans.autotrans.enable-redis", havingValue = "true")
    public RedisCacheService redisCacheService(RedisTemplate redisTemplate, AutoTransService autoTransService) {
        RedisCacheServiceImpl redisCacheService = new RedisCacheServiceImpl();
        redisCacheService.setRedisTemplate(redisTemplate);
        redisCacheService.setStrRedisTemplate(redisTemplate);
        autoTransService.setRedisTransCache(redisCacheService);
        return redisCacheService;
    }
    @Bean(TransType.DICTIONARY+"RedisCache")
    @ConditionalOnProperty(name = "easy-trans.autotrans.enable-redis", havingValue = "true")
    public RedisCacheService<String> dicRedisCacheService(RedisTemplate redisTemplate) {
        RedisCacheServiceImpl<String> redisCacheService = new RedisCacheServiceImpl();
        redisCacheService.setRedisTemplate(redisTemplate);
        redisCacheService.setStrRedisTemplate(redisTemplate);
        return redisCacheService;
    }


    @Bean("springContextUtil")
    public SpringContextUtil springContextUtil() {
        return new SpringContextUtil();
    }
}
